/*
 * @描述:联动过滤表单组件
 * @Author: /songzi
 * @Date: 2019-08-02 09:57:51
 * @Last Modified by: songzi
 * @Last Modified time: 2020-02-07 18:25:45
 */
import React, { PureComponent } from 'react';
import { Select } from 'antd';
import RenderInput, { renderOptions } from './renderInputType';
// import RenderInput from './RenderInput';
import styles from './ConnectionForm.less';

/**
 * @description 解析prop传过来的value对象为组件可用
 * @param {*} valueObj
 * @returns
 */
const ravValue = valueObj => {
  const { field } = valueObj;
  const fieldArr = field.split('.');
  const fieldLast = fieldArr.pop();
  return { ...valueObj, fieldOptionValue: fieldLast };
};

const revOptionName = optionItem => {
  const eventName = optionItem.event_name;
  const { groupName, name } = optionItem;
  const setVal = `${groupName}.${eventName ? `${eventName}.` : ''}${name}`;
  return setVal;
};

/**
 * @description 过滤出符合条件的datatype对应的input配置项
 * @param {*} dataTypeconfig
 * @param {*} options
 * @param {*} field
 * @returns
 */
const fiterDataType = (dataTypeconfig, dataType) => {
  const dataTypeOption = dataTypeconfig[dataType] || [];
  return dataTypeOption;
};

/**
 * @description 把function配置以及props 转换成inputconfig
 * @param {*} inputType input类型
 * @param {*} inputProps 表单组件默认属性
 * @param {*} getParams 异步获取数据的方法
 * @param {*} inputOption select的option数据
 * @returns
 */
const revDataTypeInputConfig = (inputType, inputProps, getParams, inputOption) => {
  const { type, inputProps: defInputProps } = inputType;
  const inputConfig = { type, inputProps: { ...defInputProps, ...inputProps } };
  //   const input = 'input'; // input控件
  //   const selectMultiple = 'selectMultiple'; // 多选控件
  //   const select = 'select'; // 普通单选控件
  //   const rangePicker = 'rangePicker'; // 区间时间选择控件
  //   const betweenInput = 'betweenInput'; // 区间input控件
  //   const relativeInput = 'relativeInput'; // 相对当前时间点控件
  //   const relativeBetweenInput = 'relativeBetweenInput'; // 相对当前时间区间控件
  //   const relativeEvenTimeInput = 'relativeEvenTimeInput'; // 相对事件发生时间控件
  const { paramsOptionList } = inputOption;
  if (/select/.test(type)) {
    if (typeof getParams === 'function') {
      inputConfig.inputProps.onFocus = getParams;
    }
    inputConfig.optionList = { list: paramsOptionList };
    // inputConfig.optionValue = paramsOptionList.map(item => item.value);
    // inputConfig.optionName = paramsOptionList.map(item => item.name);
  } else if (type === 'autoComplete') {
    if (typeof getParams === 'function') {
      inputConfig.inputProps.onFocus = getParams;
    }
    inputConfig.dataSource = paramsOptionList;
  }
  return inputConfig;
};

class ConnectionForm extends PureComponent {
  /**
   * @description  react生命周期函数（从props中获取state）
   * @author songs
   * @date 2019-08-02
   * @static
   * @param {*} nextProps
   * @returns
   * @memberof ConnectionForm
   */
  static getDerivedStateFromProps(nextProps, oldeProps) {
    const { options } = nextProps;
    if ('value' in nextProps) {
      return {
        options,
        ...(nextProps.value || {})
      };
    }
    return null;
  }

  constructor(props) {
    super(props);
    const value = props.value || props.defaultValue || {};

    const usedVal = ravValue(value);
    // const { options = [], funcConfig } = this.props;
    this.state = {
      funcName: usedVal.function || '',
      field: usedVal.field || '',
      fieldOptionValue: usedVal.fieldOptionValue || '',
      dataType: usedVal.dataType,
      params: usedVal.params || [],
      paramsOptionList: []
    };
  }

  componentDidMount() {
    this.checkGetParmas();
  }

  checkGetParmas = () => {
    // import { config, functionInput };
    const { funcConfig, getParams, options } = this.props;
    const { functionInput } = funcConfig;
    const { fieldOptionValue, funcName, paramsOptionList } = this.state;
    const { setParamsOption } = this;
    const inputTypeConfig = functionInput[funcName];
    // 获取事件属性可选values
    const selectValuesTypes = ['select', 'autoComplete'];
    const needGetValues = inputTypeConfig && selectValuesTypes.includes(inputTypeConfig.type);
    if (needGetValues && getParams && (!paramsOptionList || !paramsOptionList.length)) {
      const optionsItem = options.filter(item => item.name === fieldOptionValue)[0];
      getParams(optionsItem, setParamsOption);
    }
  };

  setParamsOption = paramsOptionList => {
    this.setState({ paramsOptionList });
  };

  /**
   * @description  functionname表单 change事件
   * @param {*} value
   * @returns
   */
  handleFuncNameChange = value => {
    const {
      funcConfig: { functionInput }
    } = this.props;
    const { triggerChange, checkGetParmas } = this;
    const inputTypeConfig = functionInput[value];
    this.setState({ funcName: value, params: [] }, () => {
      checkGetParmas();
      if (!inputTypeConfig) {
        triggerChange();
      }
    });
  };

  /**
   * @description 字段表单change事件
   * @param {*} value
   */
  handleNameChange = value => {
    const {
      options = [],
      funcConfig: { config }
    } = this.props;
    const optionItem = options.filter(item => item.name === value)[0];
    const dataType = optionItem.has_dict ? 'dict' : optionItem.data_type;
    const dataTypeOption = fiterDataType(config, dataType);
    const funcName = dataTypeOption[0] ? dataTypeOption[0].funcName : '';
    const field = revOptionName(optionItem);
    this.setState({ field, fieldOptionValue: value, dataType, paramsOptionList: [] }, () => {
      this.handleFuncNameChange(funcName);
    });
  };

  /**
   * @description 参数表单change事件
   * @param {*} value
   */
  handleParamsChange = value => {
    const { triggerChange } = this;
    const valueType = value.constructor.name;
    const setStateObj = { params: value };
    if (valueType === 'SyntheticEvent') {
      setStateObj.params = [value.target.value];
    }
    if (valueType === 'String') {
      setStateObj.params = [value];
    }
    this.setState(setStateObj, triggerChange);
  };

  /**
   * @description 最终表单change通知事件
   */
  triggerChange = () => {
    const { funcName, field, params, dataType } = this.state;
    const { onChange } = this.props;
    if (onChange) {
      onChange({ field, function: funcName, params, dataType });
    }
  };

  getGroupsOptions = (options, valueFiled, nameFiled, groupName, groups) => {
    if (groups && groups.length) {
      const groupOpts = groups.map(group => {
        const groupOptions = options.filter(item => item[groupName] === group.value);
        return (
          <Select.OptGroup key={group.value} label={group.name}>
            {renderOptions(groupOptions, valueFiled, nameFiled)}
          </Select.OptGroup>
        );
      });
      return groupOpts;
    }
    return renderOptions(options, valueFiled, nameFiled);
  };

  filterOption = (input, option) => {
    const { children } = option.props;
    const { value: optValue } = option.props;
    if (children instanceof Array) {
      const opts = children.find(
        oitem => oitem.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 || oitem.props.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
      );
      return opts && opts.length > 0;
    }
    if (children.toLowerCase().indexOf(input.toLowerCase()) >= 0) return true;
    if (optValue !== 'all' && optValue.toLowerCase().indexOf(input.toLowerCase()) >= 0) return true;
    return false;
  };

  render() {
    const {
      size,
      options,
      groupName = 'groupName',
      groups,
      funcConfig: { functionInput, config }
    } = this.props;
    const { funcName, fieldOptionValue, params, paramsOptionList } = this.state;
    let { dataType } = this.state;
    if (!dataType && options.length > 0) {
      const field = options.find(item => item.name === fieldOptionValue);
      if (field) dataType = field.data_type;
    }

    const { handleParamsChange, checkGetParmas, filterOption } = this;

    /**
     * @description 判断是否需要渲染parmas表单组件并输出组件
     * @returns
     */
    const needRnderInput = () => {
      const configInfo = functionInput[funcName];
      if (!configInfo) return <></>;
      const inputConfig = revDataTypeInputConfig(configInfo, { onChange: handleParamsChange, value: params }, checkGetParmas, {
        paramsOptionList
      });
      return (
        <div className={styles.connectionFormItem}>
          <RenderInput {...inputConfig}></RenderInput>
        </div>
      );
    };

    return (
      <div className="clearfix">
        <div className={styles.connectionFormItem}>
          <Select showSearch filterOption={filterOption} value={fieldOptionValue} style={{ width: 180 }} onChange={this.handleNameChange}>
            {this.getGroupsOptions(options, 'name', 'cname', groupName, groups)}
          </Select>
        </div>
        <div className={styles.connectionFormItem}>
          <Select title="funcName" value={funcName} size={size} style={{ width: 180 }} onChange={this.handleFuncNameChange}>
            {options.length && renderOptions(fiterDataType(config, dataType), 'funcName', 'cname')}
          </Select>
        </div>
        {needRnderInput()}
      </div>
    );
  }
}

export default ConnectionForm;
